#include <jni.h>
#include <GLES3/gl3.h>
#include <gles_utility.h>
#include <string.h>
#include <android_utility.h>

#ifdef __cplusplus
extern "C" {
#endif

#define VERTEX_POS_SIZE       3 // x, y and z
#define VERTEX_COLOR_SIZE     4 // r, g, b, and a

typedef struct {
    GLuint programObject;
    // VertexBufferObject Ids
    GLuint vboIds[2];
    // VertexArrayObject Id
    GLuint vaoId;
} SampleBean;

static SampleBean samBean;

JNIEXPORT void JNICALL
Java_com_andova_egl_VAO_00024Companion_surfCreated(JNIEnv *, jobject) {
    memset(&samBean, 0, sizeof(SampleBean));
    const char vShaderStr[] =
            "#version 300 es                            \n"
            "layout(location = 0) in vec4 a_position;   \n"
            "layout(location = 1) in vec4 a_color;      \n"
            "out vec4 v_color;                          \n"
            "void main()                                \n"
            "{                                          \n"
            "   v_color = a_color;                      \n"
            "   gl_Position = a_position;               \n"
            "}";
    const char fShaderStr[] =
            "#version 300 es            \n"
            "precision mediump float;   \n"
            "in vec4 v_color;           \n"
            "out vec4 o_fragColor;      \n"
            "void main()                \n"
            "{                          \n"
            "   o_fragColor = v_color;  \n"
            "}";
    samBean.programObject = glesInitialize(vShaderStr, fShaderStr);
    // 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
    GLfloat vertices[3 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE)] =
            {
                    0.0F, 0.5F, 0.0F,       // v0
                    1.0F, 0.0F, 0.0F, 1.0F, // c0
                    -0.5F, -0.5F, 0.0F,     // v1
                    0.0F, 1.0F, 0.0F, 1.0F, // c1
                    0.5F, -0.5F, 0.0F,      // v2
                    0.0F, 0.0F, 1.0F, 1.0F, // c2
            };
    // Index buffer data
    GLushort indices[3] = {0, 1, 2};
    LOGI("sample bean -> programObject:%d, vbo[0]:%d, vbo[1]:%d, vao:%d", samBean.programObject,
         samBean.vboIds[0], samBean.vboIds[1], samBean.vaoId);
    // Generate VBO Ids and load the VBOs with data
    glGenBuffers(2, samBean.vboIds);
    glBindBuffer(GL_ARRAY_BUFFER, samBean.vboIds[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, samBean.vboIds[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // Generate VAO Id
    glGenVertexArrays(1, &samBean.vaoId);
    // Bind the VAO and then setup the vertex attributes
    glBindVertexArray(samBean.vaoId);
    LOGI("sample bean -> programObject:%d, vbo[0]:%d, vbo[1]:%d, vao:%d", samBean.programObject,
         samBean.vboIds[0], samBean.vboIds[1], samBean.vaoId);

    // 为何还要写下面两句
    glBindBuffer(GL_ARRAY_BUFFER, samBean.vboIds[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, samBean.vboIds[1]);

    glEnableVertexAttribArray(0); // a_position
    glEnableVertexAttribArray(1); // a_color

    glVertexAttribPointer(0, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE,
                          sizeof(GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE), nullptr);
    glVertexAttribPointer(1, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE,
                          sizeof(GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE),
                          (const void *) (VERTEX_POS_SIZE * sizeof(GLfloat)));
    // Reset to the default VAO
    glBindVertexArray(0);

    glClearColor(1.0F, 1.0F, 1.0F, 0.0F);
}

JNIEXPORT void JNICALL
Java_com_andova_egl_VAO_00024Companion_surfChanged(JNIEnv *, jobject, jint w, jint h) {
    glViewport(0, 0, w, h);
}

JNIEXPORT void JNICALL
Java_com_andova_egl_VAO_00024Companion_drawFrame(JNIEnv *, jobject) {
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(samBean.programObject);
    glBindVertexArray(samBean.vaoId);
//    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr);
    // Return to the default VAO
    glBindVertexArray(0);
}

#ifdef __cplusplus
}
#endif